package net.fdukedom.epicurus.pm.client.panels;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;

import org.jdom.Element;

import java.util.List;

import net.fdukedom.epicurus.client.ClientSession;
import net.fdukedom.epicurus.client.connection.MessageServiceWrapper;
import net.fdukedom.epicurus.client.ui.GUIDispatcher;
import net.fdukedom.epicurus.domain.entity.User;
import net.fdukedom.epicurus.domain.util.UserHelper;
import net.fdukedom.epicurus.pm.client.PMClientPlugin;
import net.fdukedom.epicurus.pm.domain.entity.PrivateMessage;
import net.fdukedom.epicurus.pm.domain.util.PrivateMessageHelper;
import net.fdukedom.epicurus.pm.ws.MessageXMLWrapper;
import net.fdukedom.epicurus.resource.ResourceDispatcher;
import net.fdukedom.epicurus.service.interaction.IdentificationRequest;
import net.fdukedom.epicurus.service.interaction.IdentificationRequestWriter;
import net.fdukedom.epicurus.service.interaction.ResponseReader;

/**
 * Alexander Kirakozov
 * 
 * @author Alexander Kirakozov
 * 
 */
public class InboxPanel extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * 
	 * @author Alexander Kirakozov
	 * 
	 */
	class JTableButtonRenderer implements TableCellRenderer {
		private TableCellRenderer defaultRenderer;

		public JTableButtonRenderer(TableCellRenderer renderer) {
			defaultRenderer = renderer;
		}

		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row,
				int column) {
			if (value instanceof Component)
				return (Component) value;
			return defaultRenderer.getTableCellRendererComponent(table, value,
					isSelected, hasFocus, row, column);
		}
	}

	/**
	 * 
	 * @author Alexander Kirakozov
	 * 
	 */
	class JTableMouseListener implements MouseListener {
		private JTable table;

		private void forwardEventToButton(MouseEvent e) {
			Object value;
			JButton button;
			MouseEvent buttonEvent;
			TableColumnModel columnModel = table.getColumnModel();
			int column = columnModel.getColumnIndexAtX(e.getX());
			int row = e.getY() / table.getRowHeight();

			if (row < table.getRowCount() && row >= 0
					&& column < table.getColumnCount() && column > 0) {
				value = table.getValueAt(row, column);
				if (value instanceof JButton) {

					button = (JButton) value;
					if (e.getID() == MouseEvent.MOUSE_CLICKED) {
						buttonEvent = (MouseEvent) SwingUtilities
								.convertMouseEvent(table, e, button);
						button.dispatchEvent(buttonEvent);
					}
				}
			}

			table.repaint();
		}

		public JTableMouseListener(JTable table) {
			this.table = table;
		}

		public void mouseClicked(MouseEvent e) {
			forwardEventToButton(e);
		}

		public void mouseEntered(MouseEvent e) {
		}

		public void mouseExited(MouseEvent e) {
			JButton button;

			for (int i = 0; i < table.getRowCount(); i++) {
				button = (JButton) table.getValueAt(i, 2);
				button.setForeground(Color.BLUE);
			}
			table.repaint();
		}

		public void mousePressed(MouseEvent e) {
		}

		public void mouseReleased(MouseEvent e) {
		}
	}

	/**
	 * 
	 * @author Alexander Kirakozov
	 * 
	 */
	class JTableMouseMoutionListener implements MouseMotionListener {
		private JTable table;

		public JTableMouseMoutionListener(JTable table) {
			this.table = table;
		}

		public void mouseDragged(MouseEvent e) {
		}

		public void mouseMoved(MouseEvent e) {
			Object value;
			JButton button;
			TableColumnModel columnModel = table.getColumnModel();
			int column = columnModel.getColumnIndexAtX(e.getX());
			int row = e.getY() / table.getRowHeight();

			for (int i = 0; i < table.getRowCount(); i++) {
				button = (JButton) table.getValueAt(i, 2);
				button.setForeground(Color.BLUE);
			}
			if (row < table.getRowCount() && row >= 0
					&& column < table.getColumnCount() && column > 0) {
				value = table.getValueAt(row, column);
				if (value instanceof JButton) {
					button = (JButton) value;

					button.setForeground(Color.BLACK);
				}
			}

			table.repaint();
		}
	}

	private class JButtonMouseListener implements MouseListener {
		/**
		 * Corresponding Message ID
		 */
		private int msgID;

		public JButtonMouseListener(int msgID) {
			this.msgID = msgID;
		}

		public void mouseClicked(MouseEvent arg0) {
			PrivateMessage msg = PrivateMessageHelper.getInstance()
					.findByIdandUser(msgID,
							ClientSession.getInstance().getUser());
			msg.setIsRead(true);
			Map<String, Object> parameters = new HashMap<String, Object>();

			parameters.put(PMClientPlugin.PARAMETER_MESSAGE_ID, msgID);
			GUIDispatcher.getInstance().showPage(PMClientPlugin.PLUGINNAME,
					PMClientPlugin.VIEW_MESSAGE_PAGE, parameters);
		}

		public void mousePressed(MouseEvent arg0) {
		}

		public void mouseReleased(MouseEvent arg0) {
		}

		public void mouseEntered(MouseEvent arg0) {
		}

		public void mouseExited(MouseEvent arg0) {
		}
	}

	/**
	 * Model for table plugin view
	 * 
	 * @author Alexander Kirakozov
	 */
	class MessageTableModel extends AbstractTableModel {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		/**
		 * Table data
		 */
		private Object[][] data;

		/**
		 * Column names
		 */
		private String[] columnNames;

		/**
		 * Constructor
		 * 
		 */
		public MessageTableModel() {
			ResourceBundle bundle = ResourceDispatcher.getInstance().getBundle(
					"bundles.pm.Inbox");
			columnNames = new String[3];

			columnNames[0] = bundle.getString("pm.inbox.from");
			columnNames[1] = bundle.getString("pm.inbox.date");
			columnNames[2] = bundle.getString("pm.inbox.title");
			loadMessageInfo();
		}

		/**
		 * Returns rows count
		 */
		public int getRowCount() {
			if (data != null) {
				return data.length;
			}
			return 0;
		}

		/**
		 * Returns columns count
		 */
		public int getColumnCount() {
			return columnNames.length;
		}

		/**
		 * Returns cell value
		 */
		public Object getValueAt(int arg0, int arg1) {
			return data[arg0][arg1];
		}

		/**
		 * Return column name
		 */
		public String getColumnName(int col) {
			return columnNames[col];
		}

		/**
		 * Load information about plugins to DB
		 */
		public void loadMessageInfo() {
			User user = ClientSession.getInstance().getUser();
			List<PrivateMessage> messages = PrivateMessageHelper.getInstance()
					.findByRecepient(user);
			data = new Object[messages.size()][3];

			for (int i = 0; i < messages.size(); i++) {
				PrivateMessage msg = messages.get(i);
				data[i][0] = msg.getFrom().getName();
				data[i][1] = DateFormat.getDateTimeInstance().format(
						msg.getCreated());

				JButton button = new JButton(msg.getTitle());
				button.setBackground(Color.WHITE);
				button.addMouseListener(new JButtonMouseListener(msg.getId()));
				data[i][2] = button;
			}

			fireTableDataChanged();
		}

		public Class getColumnClass(int column) {
			return getValueAt(0, column).getClass();
		}
	}

	/**
	 * 
	 * @author Alexander Kirakozov
	 * 
	 */
	private class UpdateActionListener extends AbstractAction {

		public void actionPerformed(ActionEvent arg0) {
			User user = ClientSession.getInstance().getUser();
			IdentificationRequestWriter request = new IdentificationRequestWriter(
					IdentificationRequest.ID_UPDATE);
			Date lastMsgDate = PrivateMessageHelper.getInstance().getLastDate(
					user);

			if (lastMsgDate != null) {
				request.setTextParameter(DateFormat.getDateTimeInstance()
						.format(lastMsgDate));
			}
			request.setEmail(user.getEmail());
			request.setPassword(user.getPassword());
			request.setPluginName(PMClientPlugin.PLUGINNAME);

			MessageServiceWrapper service = new MessageServiceWrapper();
			String xmlResponse = service.sendMessage(request.toString());

			ResponseReader reader = new ResponseReader(xmlResponse);

			if (reader.getStatus()) {
				Element result = reader.getResult();
				List<Element> messages = result
						.getChildren(MessageXMLWrapper.MESSAGE);

				for (int i = 0; i < messages.size(); i++) {
					MessageXMLWrapper msgWrap = new MessageXMLWrapper(messages
							.get(i));
					PrivateMessage message = new PrivateMessage();

					User from = UserHelper.getInstance().findByName(
							msgWrap.getAdressee());
					if (from == null) {
						from = new User();

						from.setName(msgWrap.getAdressee());
						UserHelper.getInstance().saveUser(from);
					}

					message.setFrom(from);
					message.setBody(msgWrap.getBody());
					message.setTitle(msgWrap.getTitle());
					message.setTo(user);
					message.setIsRead(msgWrap.isReaded());
					try {
						message.setCreated(msgWrap.getCreated());
					} catch (ParseException e) {
						GUIDispatcher.getInstance().showErrMessage(
								"Message has incorrect date format!");
					}

					if (i != messages.size() - 1
							|| !PrivateMessageHelper.getInstance().getLastDate(
									user).equals(message.getCreated())) {
						PrivateMessageHelper.getInstance().savePrivateMessage(
								message);
					}
				}
				messageModel.loadMessageInfo();
				GUIDispatcher.getInstance().showPage(PMClientPlugin.PLUGINNAME,
						PMClientPlugin.INBOX_PAGE, null);
			} else {
				GUIDispatcher.getInstance().showErrMessage(reader.getMessage());
			}
		}
	}

	/**
	 * Messages table model
	 */
	private MessageTableModel messageModel;

	/**
	 * Constructor
	 */
	public InboxPanel() {
		init();
	}

	/**
	 * Initialize method
	 */
	private void init() {
		// Table
		messageModel = new MessageTableModel();
		JTable table = new JTable(messageModel);
		TableCellRenderer defaultRenderer = table
				.getDefaultRenderer(JButton.class);

		table.setDefaultRenderer(JButton.class, new JTableButtonRenderer(
				defaultRenderer));
		table.addMouseListener(new JTableMouseListener(table));
		table.addMouseMotionListener(new JTableMouseMoutionListener(table));
		table.setRowHeight(20);

		// Buttons
		JPanel panel = new JPanel();
		JButton button = new JButton("Update");
		button.addActionListener(new UpdateActionListener());
		panel.add(button);

		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		add(table.getTableHeader());
		add(table);
		add(panel);
	}
}
